package cate.game.role.res.guild.po.my.skill;

import cate.common.table.d.GDGuild;
import cate.common.table.d.GDHero;
import cate.common.table.guild.GuildSkillRow;
import cate.game.attr.FightAttr;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.RoleDependent;
import cate.game.role.res.guild.po.my.skill.msg.GuildSkillChangeResp;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;

import java.util.*;
import java.util.stream.Collectors;

public class GuildPVPSkill extends RoleDependent implements GuildSkillOperation {

    @NoteField(value = "不同职业下的技能培养", detail = "Map<Job,order>")
    public Map<Byte, GuildJobSkill> jobSkillStatus;

    @NoteField(value = "不同职业下重置记录", detail = "Map<Job,haveBackedOrNot>")
    public List<Byte> jobSkillBakeRecord;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (jobSkillStatus == null) {
            jobSkillStatus = new HashMap<>();
            for (byte job : GDHero.Job.ALL) {
                jobSkillStatus.put(job, new GuildJobSkill(job));
            }
        }
        for (Map.Entry<Byte, GuildJobSkill> entry : jobSkillStatus.entrySet()) {
            entry.getValue().job = entry.getKey();
        }
        jobSkillStatus.values().forEach(job -> job.initialize(role));
        if (jobSkillBakeRecord == null) {
            jobSkillBakeRecord = new LinkedList<>();
        }
    }

    @Override
    public boolean match(byte type) {
        return type == GDGuild.Skill.PVP_SKILL_TYPE;
    }

    @Override
    public void upgrade(byte type, int order, byte job, MyGuildSkillPO myGuildSkillPO) {
        if (job == GDHero.Job.NULL || !GDHero.Job.valid(job)) {
            role.getGame().notice.message(role, "职业不存在");
            return;
        }
        GuildJobSkill jobStatus = jobSkillStatus.get(job);
        if (!jobStatus.map.containsKey(order)) {
            jobStatus.map.put(order, 0);
        }

        int level = jobStatus.map.get(order);

        GuildSkillRow currentRow = role.getGame().table.guild.skill.onGetRow(type, job, order, level);
        GuildSkillRow nextRow = role.getGame().table.guild.skill.onGetRow(type, job, order, level + 1);
        if (nextRow == null) {
            role.getGame().notice.message(role, "当前版本已经满级");
            return;
        }

        int floor = myGuildSkillPO.normal.onGetJobSkillFloor(job);
        if (floor <= 0 || floor < nextRow.floorRequire) {
            role.getGame().notice.message(role, "继续点亮技能需要所有职业技能达到" + nextRow.floorRequire + "层");
            return;
        }

        if (!jobStatus.isValidForUpgrade(nextRow.selfSkillLevel)) {
            role.getGame().notice.message(role, "需要本职业所有属性达到" + nextRow.selfSkillLevel + "级");
            return;
        }

        if (!isValidForUpgrade(nextRow.otherSkillLevel)) {
            role.getGame().notice.message(role, "需要任意3职业的所有属性达到" + nextRow.otherSkillLevel + "级");
            return;
        }

        EcResult<MixResItem> consumeRes = new MixRes(currentRow.costStr)
                .consume(role, null);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return;
        }
        jobStatus.map.put(nextRow.order, nextRow.level);
        noticeUpdate(type, job, nextRow.order, nextRow.level);
        role.getHistory().action.guildPvpSkill(job, nextRow.level);
        role.getRes().guild.active.addActive(GDGuild.activeTask.LIGHT_GUILD_SKILL);
    }

    private boolean isValidForUpgrade(int otherSkillLevel) {
        int num = 0;
        for (byte job : jobSkillStatus.keySet()) {
            num += jobSkillStatus.get(job).isValidForUpgrade(otherSkillLevel) ? 1 : 0;
        }
        return num >= GDGuild.Skill.PVP_UPGRADE_CONDITION_ON_OTHER_NUM;
    }

    private void noticeUpdate(byte type, byte job, int order, int level) {
        role.sendNow(new GuildSkillChangeResp(type, job, order, level));
    }

    @Override
    public void back(byte type, byte job, MyGuildSkillPO myGuildSkillPO) {
        GuildJobSkill jobStatus = jobSkillStatus.get(job);
        if (jobStatus == null) {
            role.getGame().notice.message(role, "当前职业不存在");
            return;
        }
        boolean firstBack = !jobSkillBakeRecord.contains(job);
        jobStatus.back(firstBack);
    }

    @Override
    public FightAttr onGetAttr(byte type, byte job, MyGuildSkillPO myGuildSkillPO) {
//        if (myGuildSkillPO.normal.onGetJobSkillFloor(job) < GDGuild.Skill.PVP_OPEN_NORMAL_LEVEL) {
//            return new FightAttr();
//        }
        GuildJobSkill jobStatus = jobSkillStatus.get(job);
        if (jobStatus == null) {
            return new FightAttr();
        }

        return jobStatus.onGetAttr();
    }

    @Override
    public List<Integer> onGetSkill(byte type, byte job, MyGuildSkillPO myGuildSkillPO) {
//        if (myGuildSkillPO.normal.onGetJobSkillFloor(job) < GDGuild.Skill.PVP_OPEN_NORMAL_LEVEL) {
//            return new ArrayList<>();
//        }
        GuildJobSkill jobStatus = jobSkillStatus.get(job);
        if (jobStatus == null) {
            return new ArrayList<>();
        }

        return jobStatus.onGetList();
    }

    @Override
    public void gmHighestLevel() {
        List<GuildSkillRow> typeList = role.getGame().table.guild.skill.getList().stream()
                .filter(row -> this.match(row.type))
                .collect(Collectors.toList());
        for (GuildJobSkill jobSkill : jobSkillStatus.values()) {
            jobSkill.gmHighestLevel(typeList);
        }
    }

    @Override
    public void gmRebuildAll() {
        jobSkillStatus = new HashMap<>();
        for (byte job : GDHero.Job.ALL) {
            jobSkillStatus.put(job, new GuildJobSkill(job));
        }
        jobSkillStatus.entrySet().removeIf(entry -> entry.getKey() == GDHero.Job.NULL);
        jobSkillStatus.values().forEach(job -> job.initialize(role));
    }
}
